# -*- coding: utf_8 -*-
# @Create   : 2021/8/18 15:11
# @Author   : yh
# @Remark   : 视频组
import logging
import time
from typing import Union

from mxsoftpy import DB
from mxsoftpy.exception import ParamsError, DBError, DataError

from model.common.VideoManage.VideoQuality.video_group import VideoGroupModel


class VideoGroupDB(DB):

    def use_keys(self) -> list:
        """
        获取所有在用的视频组
        """
        return self.tree.open('VideoQuality', 'VideoGroup', file='IOT'
                              ).filter(state=1, order_by='create_time')[1]

    def _check_parent_code(self, parent_code: int) -> None:
        """
        用于校验插入数据时选择的parent_code是否合法
        """
        if parent_code != '0':
            if parent_code not in self.use_keys():
                raise ParamsError('parent_code不存在或已停用')

    def __group_name_duplicate_check(self, name: str, code: str = None):
        """
        校验分组名称是否重复
        """
        tree = self.tree.open('VideoQuality', 'VideoGroup', file='IOT')
        _, res_list = tree.filter(name=name, state=1)
        if res_list and res_list[0] != code:
            logging.error('新增视频组时：校验name是否合法时发生重名')
            raise ParamsError("新增的分组名称已存在")

    def create(self, **kwargs) -> int:
        """
        插入一条视频组数据到数据库
        """
        self._check_parent_code(kwargs['parent_code'])
        self.__group_name_duplicate_check(kwargs['name'])
        kwargs = VideoGroupModel(**kwargs).dict()
        try:
            code = self.tree.insert_key_items(kwargs)
            logging.info('新增了一个视频组，视频组code：%s' % code)
            logging.debug('新增的视频详情：%s' % str(kwargs))
        except DBError:
            logging.error('新增视频组出错,视频内容如下%s' % str(kwargs))
            raise DataError('新增视频失败')
        return code

    def group_dict(self) -> dict:
        """
        返回所有视频组数据
        """
        use_keys = self.use_keys()
        data_dict = self.tree.sub_items(key_list=use_keys) if use_keys else dict()
        res_dict = dict()
        for key in use_keys:  # 按照创建时间排序
            res_dict[key] = data_dict[key]
        return res_dict
        # return self.tree.sub_items(key_list=use_keys) if use_keys else dict()

    def _get_children_group(self, group_list, data_dict):
        """
        获取组下所有的子组列表
        """
        state = 0
        for code in list(data_dict.keys()):
            if data_dict[code]['parent_code'] in group_list:
                group_list.append(code)
                del data_dict[code]
                state = 1
        if state == 1:
            return self._get_children_group(group_list,data_dict)
        else:
            return group_list

    def _check_del_code(self, del_code: str) -> list:
        """
        检查数据是否可以删除
        """
        from db.common.VideoManage.VideoQuality.video import VideoDB  # 在函数内导包，以防止循环导包

        use_keys = self.use_keys()
        sub_items = self.tree.sub_items(key_list=use_keys, prop_list=['parent_code']) if use_keys else dict()
        group_list = [del_code]
        group_list = self._get_children_group(group_list, sub_items)
        videos = VideoDB().simple_list(group_code__in=group_list)
        if videos:
            raise ParamsError('该节点或其子节点存在视频源，无法删除')
        return group_list

    def delete(self, del_code: str) -> str:
        """
        删除视频组
        """
        group_list = self._check_del_code(del_code)

        try:
            for del_group in group_list:    # 将组下所有子节点删除
                self.tree.open('VideoQuality', 'VideoGroup\\%s' % del_group, file='IOT').insert_items(
                    [('state', 0), ('update_time', int(time.time()))])
        except DBError as e:
            logging.error('删除视频组%s时遇到错误, %s' % (del_code, str(e)))
            raise DataError('删除视频组%s时遇到错误, %s' % (del_code, str(e)))

        return del_code

    def items(self, code: str) -> dict:
        """
        获取单条视频组数据
        """
        try:
            self.tree.open('VideoQuality', 'VideoGroup', code, file='IOT')
        except DBError:
            raise ParamsError('获取数据失败，错误的group_code')
        return self.tree.items()

    def update(self, group_code: str, **kwargs) -> str:
        """
        更新视频组名称
        :param group_code: 视频组code
        """

        self.__group_name_duplicate_check(kwargs['name'], group_code)

        try:
            self.tree.open('VideoQuality', 'VideoGroup\\%s' % group_code, file='IOT')
        except DBError:
            raise ParamsError('获取数据失败，错误的group_code')
        try:
            code = self.tree.insert_items(kwargs)
            logging.info('更新了一个视频组，视频组code：%s，视频组内容如下：' % code)
            logging.info(str(kwargs))
        except DBError:
            logging.error('更新视频组出错,视频组内容如下%s' % str(kwargs))
            raise DataError('更新视频组出错,视频组内容如下%s' % str(kwargs))

        return kwargs['name']

    def select(self, name: str) -> dict:
        """
        根据关键词查询视频组
        :param name: 视频组名称
        """
        keys = self.tree.open('VideoQuality', 'VideoGroup', file='IOT').filter(
                                name__like='*%s*' % name, state=1, order_by='create_time')[1]
        data_dict = self.tree.sub_items(key_list=keys, prop_list=['name']) if keys else dict()
        res_dict = dict()
        for key in keys:    # 按照创建时间排序
            res_dict[key] = data_dict[key]
        return res_dict

    def find_code(self, group_name: str) -> Union[str, None]:
        """
        根据视频组名称获取code
        :param group_name: 要查询的组名
        """
        keys = self.tree.open('VideoQuality', 'VideoGroup', file='IOT').filter(state=1, name=group_name)[1]
        return keys[0] if keys else None
